import * as THREE from 'three'
import { ref } from 'vue'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer.js'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
import {
  drawingFlyLine,
  drawingDots,
  drawingProvinceLabels,
  onChange
} from './utils'
import './style.scss'

function getSize() {
  const wp = window.innerWidth / 3840;
  const hp = window.innerHeight / 2160;
  const boxP = wp < hp ? wp : hp;
  return boxP; // 大屏尺寸3840px
}

const clock = new THREE.Clock()
// const w = 3840;
// const h = 2160;
const boxP = getSize()
const w = 3840 * boxP
const h = 2160 * boxP
const FLYINGLINEGROUP = 'flyingLineGroup'
const EARTHLABEGROUP = 'earthLableGroup'
const DOTGROUP = 'dotGroup'
const PROVINCELABELGROUP = 'provinceLabelGroup'
let mixer: any = null // 动画混合器
let camera: any = null
let orbitControls: any = {}
let renderer: any = {}
let labelRenderer: any = {}
let composer: any = {}
const ended = ref(false) // 标识动画播放结束

// 场景
const scene = new THREE.Scene()

const init = () => {
  // 添加灯光
  const ambientLight = new THREE.AmbientLight('#007fc8', 5) // soft white light
  scene.add(ambientLight)
  const directionalLight2 = new THREE.DirectionalLight('#007fc8', 2)
  directionalLight2.position.set(-100, 100, 50)
  scene.add(directionalLight2)

  // Camera
  const k = w / h
  camera = new THREE.PerspectiveCamera(
    31.417275332887456,
    k,
    0.009999999776482582,
    10000000000
  )
  camera.position.set(0.6, 0.45, 2.54)

  // Renderer
  renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true
  })
  renderer.setSize(w, h)
  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.setClearColor(0xffffff, 0)
  renderer.toneMapping = THREE.ReinhardToneMapping

  labelRenderer = new CSS2DRenderer()
  labelRenderer.setSize(3840, 2160)
  labelRenderer.domElement.style.position = 'absolute'
  labelRenderer.domElement.style.top = '0px'
  labelRenderer.domElement.className = 'labelR'
  labelRenderer.domElement.style.transform = 'scale(' + boxP + ')'
  labelRenderer.domElement.style.transformOrigin = '0 0'
  labelRenderer.domElement.style.touchAction = 'none'

  // 最后项目的处理
  const renderScene = new RenderPass(scene, camera)
  const bloomPass = new UnrealBloomPass(
    new THREE.Vector2(w, h),
    1.5,
    0.4,
    0.85
  )

  const params = {
    exposure: 1,
    bloomStrength: 0.35, // 辉光强度
    bloomThreshold: 0,
    bloomRadius: 0.3
  }

  bloomPass.threshold = params.bloomThreshold
  bloomPass.strength = params.bloomStrength
  bloomPass.radius = params.bloomRadius

  // 效果组合器
  composer = new EffectComposer(renderer)
  composer.addPass(renderScene)
  composer.addPass(bloomPass)

  orbitControls = new OrbitControls(camera, labelRenderer.domElement)
  orbitControls.target.copy(scene.position)
  orbitControls.update()

  // 这允许根据材料粗糙度快速访问不同级别的模糊
  const pmremGenerator = new THREE.PMREMGenerator(renderer)
  // 预编译 equirectangular 着色器。您可以通过在纹理的网络获取期间调用此方法来加快启动速度，从而提高并发性。
  pmremGenerator.compileEquirectangularShader()
  // 让整个球发光
  new RGBELoader()
    .setDataType(THREE.UnsignedByteType) // alt: FloatType, HalfFloatType UnsignedByteType // KinoStudio2.hdr
    .load('./scene/hdr.hdr', (texture) => {
      // const envMap = pmremGenerator.fromEquirectangular(texture).texture;
      // scene.environment = envMap;

      // texture.dispose();
      // pmremGenerator.dispose();
      texture.mapping = THREE.EquirectangularReflectionMapping
      // 将加载的材质texture设置给背景和环境
      scene.environment = texture
    })
  tick()
}

/**
 * 地球飞入动画
 * @param model 模型数据
 * @param animations 动画
 * @param fn 传入的方法
 */
const playEarthAnimation = (model: any, animations: any, fn: any, showOfficeName: any, eventType: number) => {
  const object = model.getObjectByName('earthModel')
  mixer = new THREE.AnimationMixer(object)
  let duration = 0
  if (!animations && !animations.lenght) return
  for (let i = 0; i < animations.length; i++) {
    // 动画剪辑（AnimationClip）是一个可重用的关键帧轨道集，它代表动画。
    const animation: any = animations[i]
    // 返回动画操作对象
    const action = mixer.clipAction(animation)
    // 剪辑对象设置播放结束时间
    duration = duration + animation.duration
    // 暂停在最后一帧播放的状态
    action.clampWhenFinished = true
    // 只播放一次
    action.setLoop(THREE.LoopOnce).play()
  }

  mixer.addEventListener('finished', () => {
    onChange(eventType, model, fn, showOfficeName)
    ended.value = true
  })
}

const tick = () => {
  const time = clock.getDelta()
  if (mixer) mixer.update(time)
  requestAnimationFrame(tick)
  labelRenderer.render(scene, camera)
  orbitControls.update()
  composer.render()
}

init()
tick()

// console.log(ended.value);

export { renderer, labelRenderer, scene, camera, ended, playEarthAnimation }
